package service

import (
	"gin-gorm-oj/model"
	"gin-gorm-oj/utils"
	"log"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

// ProblemCreate 处理创建新问题的请求
// @Tags 管理员私有方法
// @Summary 问题创建
// @Accept json
// @Param authorization header string true "JWT_token" // 请求头参数，必填
// @Param data body utils.ProblemPost true "utils.ProblemPost" // 请求体参数，必填
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /admin/problem-create [post]
func ProblemCreate(c *gin.Context) {
	in := new(utils.ProblemPost) // 定义一个 ProblemPost 结构体实例，用于接收输入的 JSON 数据

	// 绑定请求体中的 JSON 数据到 'in' 结构体
	err := c.ShouldBindJSON(in)
	if err != nil {
		log.Println("[JsonBind Error] : ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "参数错误",
		})
		return
	}

	// 检查必要字段是否为空，若有空值则返回错误
	if in.Title == "" || in.Content == "" || in.MaxRuntime == 0 ||
		in.MaxMem == 0 || in.CategoryID == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "参数不能为空",
		})
		return
	}

	// 创建 Problem 实例以存储新问题的详细信息
	data := &model.Problem{
		Title:      in.Title,
		Content:    in.Content,
		MaxRuntime: in.MaxRuntime,
		MaxMem:     in.MaxMem,
		CategoryID: in.CategoryID,
		CreatedAt:  time.Now(),
		UpdatedAt:  time.Now(),
	}

	// 将问题信息保存到数据库
	err = utils.DB.Create(data).Error
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "Problem Create Error:" + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": map[string]interface{}{
			"id": data.ID,
		},
	})
}

// ProblemModify 处理修改已有问题的请求
// @Tags 管理员私有方法
// @Summary 问题修改
// @Param authorization header string true "JWT_token" // 请求头参数，必填
// @Param data body utils.ProblemPost true "utils.ProblemPost" // 请求体参数，必填
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /admin/problem-modify [put]
func ProblemModify(c *gin.Context) {
	// 定义 ProblemPost 结构体实例，用于接收请求中的 JSON 数据
	in := new(utils.ProblemPost)
	err := c.ShouldBindJSON(in) // 将请求体中的 JSON 数据绑定到 'in' 结构体
	if err != nil {
		log.Println("[JsonBind Error] : ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "参数错误",
		})
		return
	}

	// 检查字段是否为空，若为空则返回错误
	if in.ID == 0 || in.Title == "" || in.Content == "" || in.CategoryID == 0 ||
		in.MaxRuntime == 0 || in.MaxMem == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "参数不能为空",
		})
		return
	}
	// 初始化 Problem 结构体实例以存储更新后的问题信息
	problem := &model.Problem{
		ID:         in.ID,
		Title:      in.Title,
		Content:    in.Content,
		MaxRuntime: in.MaxRuntime,
		MaxMem:     in.MaxMem,
		UpdatedAt:  time.Now(),
	}
	// 更新数据库中指定问题的信息
	err = utils.DB.Where("id = ?", in.ID).Updates(problem).Error
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "Problem Modify Error:" + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "问题修改成功",
	})
}

// CategoryCreate 处理创建新分类的请求
// @Tags 管理员私有方法
// @Summary 分类创建
// @Param authorization header string true "JWT_token" // 请求头参数，必填
// @Param name formData string true "分类名称" // 表单参数，必填
// @Param parentId formData int false "父分类ID" // 表单参数，选填
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /admin/category-create [post]
func CategoryCreate(c *gin.Context) {
	// 获取表单中的分类名称
	name := c.PostForm("name")

	// 获取表单中的父分类 ID，并将其转换为整数类型
	parentId, _ := strconv.Atoi(c.PostForm("parentId"))

	// 创建 Category 实例，用于保存新分类的信息
	category := &model.Category{
		Name:      name,
		ParentID:  int32(parentId),
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	// 将新分类信息保存到数据库
	err := utils.DB.Create(category).Error
	if err != nil {
		log.Println("Create Category Error:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "创建分类失败",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "创建成功",
	})
}

// CategoryModify 处理修改分类的请求
// @Tags 管理员私有方法
// @Summary 分类修改
// @Param authorization header string true "JWT_token" // 请求头参数，必填
// @Param id formData string true "分类id" // 表单参数，必填
// @Param name formData string true "分类名称" // 表单参数,必填
// @Param parentId formData int false "父分类ID" // 表单参数，选填
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /admin/category-modify [put]
func CategoryModify(c *gin.Context) {
	// 获取分类id
	id := c.PostForm("id")
	// 获取分类名称
	name := c.PostForm("name")
	// 获取父分类 ID
	parentId, _ := strconv.Atoi(c.PostForm("parentId"))

	// 校验必须字段的非空
	if name == "" || id == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "参数不正确",
		})
		return
	}

	// 创建 Category 实例，用于更新分类信息
	category := &model.Category{
		Name:      name,
		ParentID:  int32(parentId),
		UpdatedAt: time.Now(),
	}

	// 更新数据库中指定分类的信息
	err := utils.DB.Where("id = ?", id).Updates(category).Error
	if err != nil {
		log.Println("Modify Category Error:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "修改分类失败",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "修改成功",
	})
}

// CategoryDelete
// @Tags 管理员私有方法
// @Summary 分类删除
// @Param authorization header string true "JWT_token" // 请求头参数，必填
// @Param id query string true "分类id" // 查询参数，必填
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /admin/category-delete [delete]
func CategoryDelete(c *gin.Context) {
	id := c.Query("id") // 从查询参数中获取分类id
	if id == "" {       // 检查 id 是否为空
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "参数不正确",
		})
		return
	}

	// 删除指定分类
	err := utils.DB.Where("id = ?", id).Delete(new(model.Category)).Error
	if err != nil {
		log.Println("Delete Category Error:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "删除失败",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "删除成功",
	})
}

// GetTestCase
// @Tags 管理员私有方法
// @Summary 测试案例列表
// @Param authorization header string true "JWT_token" // 请求头参数，必填
// @Param problem_id query string true "问题id" // 查询参数，必填
// @Param page query int false "页码" // 查询参数，选填
// @Param size query int false "每页记录数" // 查询参数，选填
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /admin/test-case [get]
func GetTestCase(c *gin.Context) {
	// 从查询参数中获取每页记录数和页码
	size, page := utils.GetSizeAndPage(c)
	if size == -1 {
		// 如果分页参数出错，返回
		return
	}

	problemId := c.Query("problem_id") // 获取问题id
	if problemId == "" {               // 检查问题id是否为空
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "问题id不能为空",
		})
		return
	}

	var count int64 // 用于存储测试案例的总数量

	data := make([]*model.TestCase, 0) // 创建切片用于存储查询结果
	tx := utils.DB.Model(new(model.TestCase)).
		Where("problem_id = ?", problemId).Count(&count)

	if c.Query("size") != "" { // 如果请求中有 size 参数，则设置分页
		tx.Offset(page).Limit(size)
	}

	err := tx.Find(&data).Error // 执行查询操作，将结果存入 data
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "Get TestCase List Error:" + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": map[string]interface{}{
			"list":  data,
			"count": count,
		},
	})
}
